package org.raftkv.raft.utils;


import org.raftkv.raft.exceptions.RaftException;
import org.raftkv.raft.pb.ConfState;
import org.raftkv.raft.pb.Entry;
import org.raftkv.raft.pb.enums.MessageType;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class Utils {

    public static List<Entry> limitSize(List<Entry> ents, long maxSize) {
        if (ents.size() == 0) {
            return ents;
        }
        long size = ents.get(0).size();
        int limit = 0;
        for (limit = 1; limit < ents.size(); limit++) {
            size += ents.get(limit).size();
            if (size > maxSize) {
                break;
            }
        }
        return new ArrayList<>(ents.subList(0, limit));
    }

    public static <T> boolean isEmpty(Collection<T> collection) {
        return collection == null || collection.size() == 0;
    }

    public static boolean isCollectionEquals(Collection a, Collection b) {
        if (isEmpty(a) && isEmpty(b)) {
            return true;
        }
        if (isEmpty(a) || isEmpty(b)) {
            return false;
        }
        return a.equals(b);
    }

    public static boolean isLocalMsg(MessageType msgt) {
        return msgt == MessageType.MsgHup || msgt == MessageType.MsgBeat || msgt == MessageType.MsgUnreachable
                || msgt == MessageType.MsgSnapStatus || msgt == MessageType.MsgCheckQuorum;
    }

    public static boolean isResponseMsg(MessageType msgt) {
        return msgt == MessageType.MsgAppResp || msgt == MessageType.MsgVoteResp || msgt == MessageType.MsgHeartbeatResp
                || msgt == MessageType.MsgUnreachable || msgt == MessageType.MsgPreVoteResp;
    }

    public static void assertConfStatesEquivalent(ConfState cs1, ConfState cs2) {
        assert cs1.equals(cs2);
    }

    public static MessageType voteRespMsgType(MessageType msgt) {
        switch (msgt) {
            case MsgVote:
                return MessageType.MsgVoteResp;
            case MsgPreVote:
                return MessageType.MsgPreVoteResp;
            default:
                throw new RaftException(String.format("not a vote message: %s", msgt));
        }
    }

    public static int payloadSize(Entry m) {
        return m.getData() == null ? 0 : m.getData().length;
    }

}
